<template>
  <div class="canvas-container-wrap">
    <canvas class="canvas-container" @mousemove="onCanvasHover"></canvas>
    <div class="label-wrap" ref="labelWrapRef">
      <div class="label">
        {{ currentPolyName }}
      </div>
    </div>
    <div class="pop-wrap" ref="popWrapRef" v-if="showBuildPop">
      <div class="build-pop">
        <BorderBox12 style="padding: 0.6rem">
          <div class="build-pop-content">
            <template v-if="buildInfo.id">
              <div class="build-name">{{ buildInfo.build_name }}</div>
              <div class="build-info-line">
                <span>楼栋编号：</span>
                <span>{{ buildInfo.build_number }}</span>
              </div>
              <div class="build-info-line">
                <span>楼层数量：</span>
                <span>{{ buildInfo.build_name }}层</span>
              </div>
              <div class="build-info-line">
                <span>楼栋住户：</span>
                <span>{{ buildInfo.layer_count }}户</span>
              </div>
              <div class="build-button-list">
                <div
                  class="build-button"
                  @click="showBuildInfoComponent('RealPic')"
                >
                  实景图
                </div>
                <div
                  class="build-button"
                  @click="showBuildInfoComponent('RichText')"
                >
                  楼栋介绍
                </div>
                <div
                  class="build-button"
                  @click="showBuildInfoComponent('Section')"
                >
                  入驻企业
                </div>
              </div>
            </template>
          </div>
        </BorderBox12>
      </div>
    </div>
  </div>
</template>

<script>
import {
  defineComponent,
  reactive,
  toRefs,
  computed,
  watch,
  toRaw,
  ref,
  nextTick,
} from "vue";
import request from "../../../common/utils/request";
import store from "../../../store/index";
import { useRoute, useRouter } from "vue-router";
import utils from "../../../common/utils/utils";
import { Modal, notification, message } from "ant-design-vue";
import {
  LoadingOutlined,
  CheckCircleOutlined,
  CloseOutlined,
} from "@ant-design/icons-vue";
import CanvasSelect from "canvas-select";
import { BorderBox12 } from "@kjgl77/datav-vue3";

let canvasHoverTimer = null;

export default defineComponent({
  name: "CanvasBackground",
  components: { CanvasSelect, BorderBox12 },
  props: {
    village: {
      type: Object,
      default: () => {},
    },
  },

  setup(props, context) {
    const route = useRoute();
    const router = useRouter();
    const state = reactive({
      // 2D鸟瞰图
      canvasInstance: null,
      canvasConfig: {},
      showCanvasContainer: false,
      labelWrapRef: null,
      currentPolyName: "",
      popWrapRef: null,
      showBuildPop: false,
      buildRealPicVisible: false,
      buildRichTextVisible: false,
      buildSectionVisible: false,
      activePoly: {},
      buildInfo: {},
      defaultOptions: [],
    });

    // 获取鸟瞰图配置信息
    const getCanvasConfig = () => {
      return new Promise((resolve, reject) => {
        request
          .get("/village", "/project/draw/get", {
            village_id: props.village.id,
          })
          .then((res) => {
            if (res.result) {
              state.canvasConfig = res.result;
              state.defaultOptions = res?.result?.draw_info || [];
            }
            resolve();
          });
      });

    };

    // 鸟瞰图初始化
    const initCanvasInstance = (url) => {
      state.canvasInstance = new CanvasSelect(".canvas-container", url);
      // 加载数据
      state.canvasInstance.setData(state.defaultOptions);
      // 0 不创建(默认)，1创建矩形，2创建多边形，3点标注，4折线标注，5圆形标注
      state.canvasInstance.createType = -1;
      state.canvasInstance.fillStyle = "transparent";
      state.canvasInstance.strokeStyle = "transparent";
      state.canvasInstance.activeStrokeStyle = "#FFF";
      state.canvasInstance.ctrlRadius = 0;
      // state.canvasInstance.scrollZoom = false;
      state.canvasInstance.readonly = true;

      state.canvasInstance.on("select", (info) => {
        console.log(state.canvasInstance);
        console.log("select", info);
        // 可对选中对参数info进行修改
        // 修改标签：info.label="hello"
        // 单个形状修改填充颜色：info.fillStyle="#0f0"
        // 然后调用instance.update()更新视图
        hidePolyLabel();
        if (info) {
          // 如果绑定了楼宇id
          if (info.build_id) {
            if (!state.activePoly.uuid || info.uuid !== state.activePoly.uuid) {
              console.log(
                "state.canvasConfig.draw_info",
                state.canvasConfig.draw_info
              );
              state.activePoly.fillStyle = "transparent";
              getBuildDetail(info.build_id);

              state.activePoly = info;
              state.activePoly.fillStyle = "rgba(41, 150, 255, 0.5)";
              state.activePoly.lineWidth = 3;
            }

            // 根据设置配置项决定点击打开方式
            let openTypeName = "";
            if (
              state.canvasConfig.setting_info &&
              state.canvasConfig.setting_info.operation_action
            ) {
              state.canvasConfig.setting_info.operation_action.forEach(
                (item) => {
                  if (item.select) {
                    openTypeName = item.label;
                  }
                }
              );
            }
            if (openTypeName == "租控剖面图") {
              // 直接打开剖面图
              showBuildInfoComponent("Section");
            } else {
              showPolyPopover();
            }
          }

          // 如果绑定了监控设备
          if (info.device_id) {
            if (info.device_type == "monitor") {
              console.log("监控设备", info.device_id);
              context.emit("showMonitorModal", info.device_id);
            }
          }
        } else {
          state.showBuildPop = false;
          state.activePoly = {};
          state.canvasConfig.draw_info.forEach((poly) => {
            poly.active = false;
            poly.fillStyle = "transparent";
            poly.lineWidth = 1;
          });
          state.canvasInstance.update();
        }
      });

      state.canvasInstance.on("updated", (result) => {
        state.canvasConfig.draw_info = [...result];
      });
    };

    const getBuildDetail = (build_id) => {
      state.buildInfo = {};
      request
        .get("/village", "/project/build/info", {
          village_id: props.village.id,
          id: build_id,
        })
        .then((res) => {
          if (res.result) {
            state.buildInfo = res.result;
          }
          context.emit("onBuildChange", build_id, res.result);
        });
    };

    const showPolyPopover = () => {
      let centerX = state.canvasInstance.mouse[0];
      let centerY = state.canvasInstance.mouse[1];
      let transform = "translate(0, -100%)";
      // 获取图片右下角坐标位置
      let picTopRight = [
        state.canvasInstance.originX + state.canvasInstance.IMAGE_WIDTH,
        state.canvasInstance.IMAGE_HEIGHT,
      ];
      if (centerX + 280 >= picTopRight[0]) {
        if (centerY < 240) {
          //如果点击位置离右上角太近，移动到鼠标左下方显示
          transform = "translate(-100%, 0)";
        } else {
          //如果点击位置离右下角太近，移动到鼠标左上方显示
          transform = "translate(-100%, -100%)";
        }
      }

      state.showBuildPop = true;
      nextTick(() => {
        state.popWrapRef.style.top = `${centerY}px`;
        state.popWrapRef.style.left = `${centerX}px`;
        state.popWrapRef.style.transform = transform;
      });
    };

    // 判断该点是否在多边形内
    const isPointInPolygon = (x, y, poly) => {
      let isInside = false;
      for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {
        const xi = poly[i][0],
          yi = poly[i][1];
        const xj = poly[j][0],
          yj = poly[j][1];
        const intersect =
          yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
        if (intersect) {
          isInside = !isInside;
        }
      }
      return isInside;
    };

    // 获取多边形中心点位置
    const getPolyCenter = (poly) => {
      let xArr = [];
      let yArr = [];
      poly.coor.forEach((item) => {
        xArr.push(item[0]);
        yArr.push(item[1]);
      });
      xArr = xArr.sort((a, b) => {
        return a - b;
      });
      yArr = yArr.sort((a, b) => {
        return a - b;
      });
      let centerX = (xArr[0] + xArr[xArr.length - 1]) / 2;
      let centerY = (yArr[0] + yArr[yArr.length - 1]) / 2;
      return { centerX, centerY };
    };

    const onCanvasHover = (e) => {
      // 有绘制数据
      if (
        state.canvasConfig.draw_info &&
        state.canvasConfig.draw_info.length > 0
      ) {
        // 加200ms防抖
        if (canvasHoverTimer) {
          clearTimeout(canvasHoverTimer);
          canvasHoverTimer = null;
        }
        canvasHoverTimer = setTimeout(() => {
          if (!state.showBuildPop) {
            togglePolyLabel();
          }
        }, 50);
      }
    };

    //鼠标当前hover坐标是否在绘制图形内，如果在则显示label
    const togglePolyLabel = () => {
      hidePolyLabel();
      // 根据画布左上角在窗口上的位置，将鼠标位置换算成在画布上的位置
      let x =
        (state.canvasInstance.mouse[0] - state.canvasInstance.originX) /
        state.canvasInstance.scale;
      let y =
        (state.canvasInstance.mouse[1] - state.canvasInstance.originY) /
        state.canvasInstance.scale;
      let hasInPolygon = false;
      let currentPoly = {};
      state.canvasConfig.draw_info.forEach((poly) => {
        poly.active = false;
        if (isPointInPolygon(x, y, poly.coor)) {
          hasInPolygon = true;
          currentPoly = poly;
          poly.fillStyle = "rgba(41, 150, 255, 0.5)";
          poly.lineWidth = 3;
        } else {
          poly.fillStyle = "transparent";
          poly.lineWidth = 1;
        }
      });
      if (hasInPolygon) {
        currentPoly.active = true;
        state.currentPolyName =
          currentPoly.build_name || currentPoly.device_name;
        if (state.activePoly.uuid == currentPoly.uuid) {
          console.log();
        } else {
          showPolyLabel(currentPoly);
        }
      }
      state.canvasInstance.update();
    };

    const showPolyLabel = (poly) => {
      let { centerX, centerY } = getPolyCenter(poly);
      // centerX&centerY 是坐标相当于画布的位置，要转换成在窗口上的位置
      centerX =
        centerX * state.canvasInstance.scale + state.canvasInstance.originX;
      centerY =
        centerY * state.canvasInstance.scale + state.canvasInstance.originY;
      // let centerX = state.canvasInstance.mouse[0];
      // let centerY = state.canvasInstance.mouse[1];
      // 根据设置配置项，是否展示楼宇名称label
      if (
        state.canvasConfig.setting_info &&
        state.canvasConfig.setting_info.is_show_mark
      ) {
        state.labelWrapRef.style.top = `${centerY}px`;
        state.labelWrapRef.style.left = `${centerX}px`;
        state.labelWrapRef.style.display = "block";
      }
    };

    const hidePolyLabel = () => {
      state.currentPolyName = "";
      state.labelWrapRef.style.display = "none";
    };

    const showBuildInfoComponent = (type) => {
      context.emit("showBuildInfoComponent", type);
    };

    const init = () => {
      nextTick(() => {
        getCanvasConfig().then(() => {
          initCanvasInstance(props.village.dimensional_bg_img);
        });
      });
    };

    init();

    return {
      ...toRefs(state),
      onCanvasHover,
      showBuildInfoComponent,
    };
  },
});
</script>

<style lang="less" scoped>
.canvas-container-wrap {
  width: 100%;
  height: 100%;
  position: relative;

  .canvas-container {
    width: 100%;
    height: 100%;
  }

  .label-wrap {
    position: absolute;
    z-index: 10;
    display: none;
    transform: translate(-50%, -150%);

    .label {
      background-color: #00a0e9;
      border-radius: 4px;
      padding: 2px 10px;
      font-weight: 600;
      max-width: 180px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      position: relative;
      color: #fff;
    }

    &::after {
      content: "";
      position: absolute;
      width: 0;
      height: 0;
      /* 箭头靠下边 */
      left: calc(50% - 6px);
      bottom: -6px;
      border-left: 6px solid transparent;
      border-right: 6px solid transparent;
      border-top: 6px solid #00a0e9;
    }
  }

  .pop-wrap {
    position: absolute;
    z-index: 10;

    .build-pop {
      width: 280px;
      height: 240px;

      .build-pop-content {
        width: 100%;
        height: 100%;
        background-color: rgba(0, 77, 145, 0.8);
        border-radius: 1rem;
        color: #fff;
        padding: 1rem 2rem;

        .build-name {
          padding-bottom: 1rem;
          font-size: 1.6rem;
          text-align: center;
          position: relative;
          margin-bottom: 1.8rem;

          &::after {
            content: "";
            position: absolute;
            width: 0;
            height: 0;
            /* 箭头靠下边 */
            left: 0;
            right: 0;
            bottom: 0;
            width: 100%;
            height: 2px;
            background: linear-gradient(to right, #285a81, #1e9fdc, #285a81);
            margin: 0 auto;
          }
        }

        .build-info-line {
          margin-top: 10px;
        }

        .build-button-list {
          margin-top: 20px;
          display: flex;
          justify-content: space-between;
          align-items: center;

          .build-button {
            width: 70px;
            height: 30px;
            position: relative;
            border: 2px solid #0389cb;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 1.2rem;
            cursor: pointer;

            &:hover {
              border: 2px solid #73d6ea;
            }
          }
        }
      }
    }
  }
}
</style>
